#ifndef MESSAGE_PASSING_H
#define MESSAGE_PASSING_H

#include "types.h"
#include "process_management.h"
#include "message_queue.h"

/* functions declarations */

/* builds a message and returns it */
void build_message(int32_t from, int32_t to, int32_t data, int32_t priority, int8_t data_flag, message* mess);

/* sends a message with data in it to the process identified by pid and returns 1 if the operation has been done successfully, 0 otherwise */ 
int32_t send_integer(int32_t to, int32_t data, int32_t priority);

/* sends a message with data in it to the process identified by pid and returns 1 if the operation has been done successfully, 0 otherwise */ 
int32_t send_string(int32_t to, char* data, int32_t priority );

/* sends the message mess to the the process to */
int32_t send(int32_t to, message mess);

/* sends the message mess to pcb */
int32_t send_pcb(PCB* pcb, message mess);

/* gets the first message of the queue, blocking call. Returns 1 if a message has been found, 0 otherwise (if blocked, it returns only once the process is waken up) or -1 in case of fatal error. */
int32_t receive_first(message* mess);

/* gets the first message from from, blocking call. Returns 1 if a message has been found, 0 otherwise (if blocked, it returns only once the process is waken up) or -1 in case of fatal error .*/
int32_t receive_from(int32_t from, message* mess);

/* gets the first message with the correct priority, blocking call. Returns 1 if a message has been found, 0 otherwise (if blocked, it returns only once the process is waken up) or -1 in case of fatal error. */
int32_t receive_priority(int32_t priority, message* mess);

/* gets the first message. If none is available, waits at most timeout ms before returning. It also returns as soon as a message arrives. Returns 1 if a message has arrived, 0 otherwise (if delayed, it returns only once the process is waken up) or -1 in case of fatal error. */
int32_t receive_first_timeout(message* mess, uint32_t timeout);

/*  gets the first message from from. It none is available, waits at most timeout ms before returning. It returns when a correct message arrives or at the end of the given time, whichever comes first. Returns 1 if a message has arrived, (if delayed, it returns only once the process is waken up) 0 if the caller is delayed or -1 in case of fatal error. */
int32_t receive_from_timeout(int32_t from, message* mess, uint32_t timeout);

/*  gets the first message with the correct priority. It none is available, waits at most timeout ms before returning. It returns when a correct message arrives or at the end of the given time, whichever comes first. Returns 1 if a message has arrived, 0 if the caller is delayed (if delayed, it returns only once the process is waken up) or -1 in case of fatal error. */
int32_t receive_priority_timeout(int32_t priority, message* mess, uint32_t timeout);

/* returns the number of messages in the queue of the PCB pcb */
int32_t get_number_messages(PCB* pcb);


#endif
